package sim.core;

import java.awt.*;

public class TcpChannel {
	public EndPoint src ;
	
	double delay ;
	Message reply ;
	EndPoint dst ;
	private int state = 0 ;
	
	TcpChannel( EndPoint src, EndPoint dst ) {
		this.src = src ; this.dst = dst ;
		delay = src.distance(dst) ;
	}
	
	TcpChannel tcpOpen( Message m ) {
		TcpTask x = new TcpTask( m, 3 * src.distance(dst) ) ;
		while( ! x.isDue && src.online && dst.online )
			Scheduler.processTasks() ;
				
		if( ! src.online || ! dst.online )
			return null ;

		state++ ;
		if( dst.online )
			m.deliverTo( this, dst.handler) ; //completes Open in dst EndPoint...
		return this ;
	}

	
	
	public boolean tcpReply( Message m ) {
		if( state != 1 ) 
			throw new RuntimeException("TcpChannel.tcpReply(). Operation Not Allowed at this stage...") ;
		
		if( ! src.online ) 
			return false ;
		
		TcpTask x = new TcpTask( m, delay ) ;
		while( ! x.isDue && dst.online && src.online )
			Scheduler.processTasks() ;

		if( ! dst.online || ! src.online )
			return false ;
		
		reply = m ;
		state++ ;
		return true ;
	}
	
	@SuppressWarnings("unchecked")
	public <T> T tcpRead() {
		if( state != 2 ) 
			throw new RuntimeException("TcpChannel.tcpRead(). Operation Not Allowed at this stage...") ;

		return (T)reply ;
	}
	
	
	
	class TcpTask extends Task {
		boolean isDue = false ;
		Message m ;
		
		TcpTask( Message m, double delay ) {
			super( delay ) ;
			this.m = m ;
		}
				
		public void run() {
			isDue = true ;
		}
		
		
		public void display( Graphics2D gu, Graphics2D gs) {
	    	if( m != null && m.isVisible() ) 
	    		m.display( src, dst, gs) ;
	    }
	}
}

	